<template>
	<view class="content" :class="{ isHidden: popupShow }">
		<view id="olMap" class="olMap" style="height: 100vh;" />

		<view id="popup" class="ol-popup" v-show="popupShow" @click="popupShow = false">
			<view class="ol-popup-content">
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:deviceName') }}</view>
					<view class="ol-popup-value">{{ popupData.name }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:deviceId') }}</view>
					<view class="ol-popup-value">{{ popupData.deviceId }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:connectionType') }}</view>
					<view class="ol-popup-value">
						{{ popupData.connectType == 10 ? $t('camera:directConnect') : popupData.connectType == 20 ?
							$t('camera:connected') : $t('camera:umpDisconnected') }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:cameraSdk') }}</view>
					<view class="ol-popup-value">
						{{ popupData.directConnectCodeId == 10000 ? $t('camera:hikvision') :
							popupData.directConnectCodeId == 10001 ? $t('camera:dahua')
								: $t('camera:ump') }}
					</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:ipAddress') }}</view>
					<view class="ol-popup-value">{{ popupData.cameraIp }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:port') }}</view>
					<view class="ol-popup-value">{{ popupData.cameraPort }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:coordinates') }}</view>
					<view class="ol-popup-value">
						{{ popupData.longitude && popupData.latitude ? popupData.longitude + ', ' + popupData.latitude :
							'' }}
					</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:height') }}</view>
					<view class="ol-popup-value">{{ popupData.height }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:azimuth') }}</view>
					<view class="ol-popup-value">{{ popupData.angle }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:deviceAddress') }}</view>
					<view class="ol-popup-value">{{ popupData.cameraAddress }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:deviceType') }}</view>
					<view class="ol-popup-value">{{ typeFormat }}</view>
				</view>
				<view class="ol-popup-list">
					<view class="ol-popup-label">{{ $t('camera:ptzControl') }}</view>
					<view class="ol-popup-value">{{ popupData.ptzControlled == 1 ? $t('search:yes') : $t('search:no') }}
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script module="ol" lang="renderjs">
	import { tagBoxSearch, getCameraDetail } from '@/api/map/index.js'

	export default {
		data() {
			return {
				map: null,
				feature: '',
				pointLayer: '',
				popupShow: false,
				popupData: {
					name: '',
					deviceId: '',
					type: ''
				}
			}
		},
		computed: {
			typeFormat() {
				const str = this.popupData.type,
					sexEnum = {
					"10": this.$t('camera:bulletCamera'),
					"20": this.$t('camera:domeCamera'),
					"30": this.$t('camera:halfDomeCamera'),
					"40": this.$t('camera:offlineVideo'),
					"50": this.$t('camera:virtualCamera'),
					"60": this.$t('search:wearingGlasses'),
					"70": this.$t('camera:uav'),
					"80": this.$t('search:helmet')
				}
				return sexEnum[str] || '--'
			}
		},
		mounted() {
			if (typeof window.ol === 'function') {
				this.initAmap()
			} else {
				const script = document.createElement('script')
				script.src = 'static/js/ol.js' //可以通过此方式导入jquery，echart库
				script.onload = this.initAmap.bind(this)
				document.head.appendChild(script)
			}
		},
		onHide() {
			this.popupShow = false
		},
		onUnload() {
			this.popupShow = false

		},
		methods: {
			initAmap() {
				/* 1. 百度投影（BD-09） */
				const bd09Projection = new ol.proj.Projection({
					code: 'BD:09',
					units: 'm',
					extent: [-20037726.37, -11708041.66, 20037726.37, 12474104.17]
				});
				ol.proj.addProjection(bd09Projection);

				/* 2. 百度专用分辨率 & tileGrid（原点 0,0；分辨率 2^(18-z)） */
				const resolutions = [];
				for (let z = 0; z <= 18; z++) resolutions[z] = Math.pow(2, 18 - z);

				const tileGrid = new ol.tilegrid.TileGrid({
					origin: [0, 0],
					resolutions
				});

				/* 3. 图层：用百度编号直接取瓦片 */
				const baiduLayer = new ol.layer.Tile({
					source: new ol.source.TileImage({
						projection: bd09Projection,
						tileGrid,
						tileUrlFunction([z, x, y]) {
							return `https://172.16.20.130:19100/map/tiles/${z}/${x}/${y}.png`;
						}
					})
				});


				const that = this
				/* 5. 地图 */
				this.map = new ol.Map({
					target: 'olMap',
					layers: [baiduLayer],
					view: new ol.View({
						projection: bd09Projection,
						center: that.lngLatToBdMerc([120.366127, 31.544753]),
						/* 4. 经纬度 → 百度墨卡托（简单线性，生产请用精确算法） */
						zoom: 17,
						minZoom: 1,
						maxZoom: 18
					})
				});

				this.map.on('singleclick', (evt) => {
					let hit = false;
					this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {
						hit = true;
						that.getCameraInfo(feature.get('id'))
					});
					// 点击空白区域可选处理
					if (!hit) console.log('点击空白');
				});

				this.map.on('moveend', () => {
					const extent = this.map.getView().calculateExtent(this.map.getSize())
					const topLeftMerc = [extent[0], extent[3]]
					const bottomRightMerc = [extent[2], extent[1]]
					const topLeftLngLat = this.bdMercToLngLat(topLeftMerc)
					const bottomRightLngLat = this.bdMercToLngLat(bottomRightMerc)
					const zoom = this.map.getView().getZoom()
					this.getTags(topLeftLngLat, bottomRightLngLat, zoom)
				})
			},
			getTags(topLeftLngLat, bottomRightLngLat, zoom) {
				tagBoxSearch({
					bottomRightLatitude: bottomRightLngLat[1],
					bottomRightLongitude: bottomRightLngLat[0],
					topLeftLatitude: topLeftLngLat[1],
					topLeftLongitude: topLeftLngLat[0],
					zoom: zoom,
					tagTypes: [10],
				}).then(res => {
					if (res.code = "00000000") {
						this.drawPoint(res.data, 1)
					}
				})
			},
			drawPoint(tagsList, type) {
				const that = this
				const pointList = tagsList.filter(i => i.longitude && i.latitude)
				if (this.feature && this.feature != '') {
					this.pointLayer.getSource().removeFeature(this.feature)
					this.map.removeLayer(this.pointLayer); //在移除图层
				}
				// 打点图标的图层
				this.pointLayer = new ol.layer.Vector({
					source: new ol.source.Vector({
						features: []
					})
				})
				this.map.addLayer(this.pointLayer)

				pointList.forEach((item, index) => {
					var iconSrc = ''
					if (type == 1) {
						iconSrc = '../../../static/images/icon_map_type1.png'
					} else if (type == 2) {
						iconSrc = '../../../static/images/icon_map_type2.png'
					}

					this.feature = new ol.Feature({
						geometry: new ol.geom.Point(that.lngLatToBdMerc([Number(item.longitude), Number(
							item.latitude)])),
						id: item.id,
						type: type
					})

					const style = new ol.style.Style({
						image: new ol.style.Icon({
							scale: 0.2,
							src: iconSrc,
							anchor: [0.48, 0.52]
						}),
						text: new ol.style.Text({
							font: 'normal 12px 黑体',
							textAlign: 'center',
							textBaseline: 'middle',
							offsetY: -20,
							offsetX: 0,
							fill: new ol.style.Fill({
								color: 'rgba(61,91,255,1)'
							}),
							padding: [0, 0, 0, 0],
							text: item.name,
						}),
						zindex: 100
					})
					this.feature.setStyle(style);
					this.pointLayer.getSource().addFeature(this.feature);
				});
			},
			getCameraInfo(id) {
				getCameraDetail({
					"ids": [id],
					"play": 0
				}).then(res => {
					if (res.code = "00000000") {
						console.log('getCameraDetail', res.data[0])
						this.popupShow = true,
							this.popupData = res.data[0]
					}
				})
			},
			lngLatToBdMerc([lng, lat]) {
				const a = 6378206.4; // 百度椭球长半轴
				const b = 6356583.8; // 百度椭球短半轴
				const e = Math.sqrt(1 - b * b / (a * a));
				const x = lng * Math.PI / 180 * a;
				const sinLat = Math.sin(lat * Math.PI / 180);
				const ts = Math.tan(Math.PI / 4 + lat * Math.PI / 360);
				const y = a * Math.log(ts * Math.pow((1 - e * sinLat) / (1 + e * sinLat), e / 2));
				return [x, y];
			},
			bdMercToLngLat([x, y]) {
				const a = 6378206.4;
				const b = 6356583.8;
				const e = Math.sqrt(1 - b * b / (a * a));
				const lng = x / a * 180 / Math.PI;

				// 归一化 y
				let t = Math.exp(-y / a);
				let lat = Math.PI / 2 - 2 * Math.atan(t);

				// 牛顿迭代 12 次即可收敛到 1e-6
				for (let i = 0; i < 12; i++) {
					const esin = e * Math.sin(lat);
					lat = Math.PI / 2 - 2 * Math.atan(t * Math.pow((1 - esin) / (1 + esin), e / 2));
				}
				return [lng, lat * 180 / Math.PI];
			},
		}
	}
</script>

<style>
@import url("@/static/css/ol.css");

.content {
	width: 100%;
	position: relative;
}

.isHidden {
	height: calc(100vh - 88rpx - 100rpx);
	overflow: hidden;
}

.ol-popup {
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	background-color: rgba(0, 0, 0, 0.2);
	padding: 40rpx;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
}

.ol-popup-content {
	width: 100%;
	max-height: 90%;
	overflow: auto;
}

.ol-popup-list {
	width: 100%;
	display: flex;
	gap: 20rpx;
	background-color: #fff;
	padding: 10rpx 16px;
	line-height: 40rpx;
}

.ol-popup-list:first-child {
	padding-top: 20rpx;
	border-top-left-radius: 12rpx;
	border-top-right-radius: 12rpx;
}

.ol-popup-list:last-child {
	padding-bottom: 20rpx;
	border-bottom-left-radius: 12rpx;
	border-bottom-right-radius: 12rpx;
}

.ol-popup-label {
	flex-shrink: 0;
}

.ol-popup-value {
	flex: 1 1 0%;
	word-break: break-all;
	text-align: right;
}
</style>